# -*- coding: utf-8 -*-

import json
import logging
import os
from typing import Dict, Any, List, Optional, Tuple, Union
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

# 确保日志配置正确
if not logging.getLogger().handlers:
    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 使用一个固定的logger名称，确保全局一致性
logger = logging.getLogger("persona_rewriter")
logger.setLevel(logging.INFO)  # 显式设置级别

# 确保logger有handler
if not logger.handlers:
    # 添加一个stream handler，直接输出到控制台
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    handler.setLevel(logging.INFO)
    logger.addHandler(handler)
    logger.propagate = True  # 允许传播到父logger


class PersonaRewriter:
    """
    人格化改写模块
    
    功能：根据医生提问与当前患者人格设定，从人格示例库中检索相似回答，指导对中性回答进行人格化改写
    """
    
    def __init__(self, model_handler=None, config=None):
        """
        初始化人格化改写器
        
        Args:
            model_handler: 模型处理器
            config: 配置对象
        """
        self.model_handler = model_handler
        self.config = config
        
        # 人格示例库路径
        self.persona_examples_path = getattr(config, 'PERSONA_EXAMPLES_PATH', 
                                           '/mnt/ssd/jsj/patient/script/method/data/persona_examples.json') if config else '/mnt/ssd/jsj/patient/script/method/data/persona_examples.json'
        
        # 人格定义文件路径
        self.personality_definition_path = '/mnt/ssd/jsj/patient/script/人格定义.json'
        
        # 示例检索参数
        self.top_k = getattr(config, 'EXAMPLE_RETRIEVAL_TOP_K', 3) if config else 3
        self.similarity_threshold = getattr(config, 'SIMILARITY_THRESHOLD', 0.6) if config else 0.6
        self.max_examples = getattr(config, 'MAX_EXAMPLES', 5) if config else 5
        self.min_examples = getattr(config, 'MIN_EXAMPLES', 2) if config else 2
        
        # 加载人格定义
        self.personality_dimensions = self._load_personality_definitions()
        
        # 加载人格示例库
        self.persona_examples = self._load_persona_examples()
        
        # 初始化语义相似度模型
        self.similarity_model = None
        self._init_similarity_model()
    
    def _init_similarity_model(self):
        """
        初始化语义相似度模型
        由于我们使用的是简单的文本匹配和关键词匹配，这里暂时不需要复杂的模型
        """
        # 这里可以根据需要初始化实际的相似度模型
        # 目前暂时设置为None，因为我们主要使用基于规则的匹配
        self.similarity_model = None
        
    def _load_personality_definitions(self) -> Dict[str, Any]:
        """
        加载人格定义.json文件
        
        Returns:
            人格维度定义字典
        """
        try:
            if not os.path.exists(self.personality_definition_path):
                logger.warning(f"人格定义文件不存在: {self.personality_definition_path}")
                return {}
            
            with open(self.personality_definition_path, 'r', encoding='utf-8') as f:
                definitions = json.load(f)
            
            logger.info(f"成功加载人格定义，包含 {len(definitions.get('personality_dimensions', {}))} 个人格维度")
            return definitions.get('personality_dimensions', {})
            
        except Exception as e:
            logger.error(f"加载人格定义失败: {str(e)}")
            return {}
    



    
    def retrieve_similar_examples(self, doctor_query: str, persona_type: str) -> List[Dict[str, Any]]:
        """
        检索与医生提问和人格类型相匹配的相似示例
        
        Args:
            doctor_query: 医生提问
            persona_type: 人格类型键（格式：性格_情绪状态）
            
        Returns:
            相似示例列表
        """
        try:
            # 1. 尝试直接获取对应人格类型的示例
            examples = self.persona_examples.get(persona_type, {})
            
            # 如果示例不存在或为空，使用回退机制
            if not examples or not examples.get('samples', []):
                fallback_key = self._fallback_persona_key(persona_type)
                if fallback_key != persona_type:
                    logger.info(f"人格类型 {persona_type} 未找到匹配示例，使用回退: {fallback_key}")
                    examples = self.persona_examples.get(fallback_key, {})
            
            # 2. 获取示例的samples列表
            samples_list = examples.get('samples', [])
            
            # 3. 扁平化示例结构
            flattened_examples = self._flatten_examples(samples_list)
            
            # 4. 如果没有找到足够的示例，考虑使用其他相关人格类型的示例
            if len(flattened_examples) < self.min_examples:
                # 获取所有复合人格类型的示例
                all_samples = []
                for key, data in self.persona_examples.items():
                    if '_' in key:
                        all_samples.extend(data.get('samples', []))
                
                # 再次扁平化并合并
                additional_examples = self._flatten_examples(all_samples)
                # 去重
                combined_examples = self._remove_duplicate_examples(flattened_examples + additional_examples)
                flattened_examples = combined_examples[:self.max_examples]
            
            # 5. 根据查询类型筛选示例
            filtered_examples = self._filter_examples_by_query_type(doctor_query, flattened_examples)
            
            # 6. 确保返回足够的示例
            if len(filtered_examples) < self.min_examples:
                # 如果筛选后示例太少，使用原始扁平化的示例
                filtered_examples = flattened_examples[:self.max_examples]
            
            return filtered_examples[:self.max_examples]
            
        except Exception as e:
            logger.error(f"检索相似示例失败: {str(e)}")
            # 返回默认的通用示例
            return self._get_default_generic_examples(doctor_query)

    def _flatten_examples(self, examples: Any) -> List[Dict[str, Any]]:
        """
        扁平化示例结构，确保返回标准格式的示例列表
        
        Args:
            examples: 输入示例数据（可能是各种格式）
            
        Returns:
            标准格式的示例列表
        """
        flattened = []
        
        try:
            if isinstance(examples, list):
                for item in examples:
                    if isinstance(item, dict):
                        # 检查是否是新格式的示例（包含doctor_query, patient_answer等字段）
                        if 'doctor_query' in item and 'patient_answer' in item:
                            # 转换为内部使用的格式
                            query_type = self._infer_query_type(item.get('doctor_query', ''))
                            patient_answer = item.get('patient_answer', '')
                            flattened_item = {
                                'query_type': query_type,
                                'doctor_query': item.get('doctor_query'),
                                'patient_answer': patient_answer,
                                'persona': item.get('persona'),
                                'entities': item.get('entities', [])
                            }
                            flattened.append(flattened_item)
                        elif 'example' in item:  # 兼容旧格式
                            # 为旧格式补充patient_answer字段，确保字段完整性
                            old_format_item = item.copy()
                            old_format_item['patient_answer'] = old_format_item.get('example', '')
                            # 推断查询类型（如果没有）
                            if 'query_type' not in old_format_item and 'doctor_query' in old_format_item:
                                old_format_item['query_type'] = self._infer_query_type(old_format_item.get('doctor_query', ''))
                            flattened.append(old_format_item)
                        else:  # 处理只有部分字段的情况
                            # 创建基本结构
                            basic_item = {
                                'query_type': '未知',
                                'doctor_query': item.get('doctor_query'),
                                'patient_answer': item.get('patient_answer', '')
                            }
                            # 如果有doctor_query，推断查询类型
                            if basic_item['doctor_query']:
                                basic_item['query_type'] = self._infer_query_type(basic_item['doctor_query'])
                            flattened.append(basic_item)
                    else:
                        # 非字典类型，尝试转换为字符串并同时设置patient_answer
                        item_str = str(item)
                        flattened.append({
                            'example': item_str,
                            'patient_answer': item_str,
                            'query_type': '未知'
                        })
            elif isinstance(examples, dict):
                # 处理可能的嵌套字典结构
                for key, value in examples.items():
                    if isinstance(value, list):
                        flattened.extend(self._flatten_examples(value))
                    elif isinstance(value, dict):
                        # 检查是否是samples结构
                        if 'samples' in value:
                            flattened.extend(self._flatten_examples(value['samples']))
            
        except Exception as e:
            logger.error(f"扁平化示例失败: {str(e)}")
        
        return flattened[:self.max_examples]

    def _infer_query_type(self, doctor_query: str) -> str:
        """
        从医生提问推断查询类型
        
        Args:
            doctor_query: 医生提问文本
            
        Returns:
            查询类型
        """
        if not doctor_query:
            return "未知"
            
        query_lower = doctor_query.lower()
        
        # 基于关键词识别查询类型
        # 注意：调整关键词优先级，确保更准确的推断
        if any(keyword in query_lower for keyword in ['多久', '什么时候', '持续', '开始', '有多长时间']):
            return "时间询问"
        elif any(keyword in query_lower for keyword in ['还有', '伴随', '其他', '同时', '除此之外']):
            return "伴随症状询问"
        elif any(keyword in query_lower for keyword in ['有没有', '是否', '是不是']):
            return "确认询问"
        elif any(keyword in query_lower for keyword in ['严重', '厉害', '程度', '有几']):
            return "程度询问"
        # 单独处理"怎么样"，避免将一般性询问误判为程度询问
        elif '怎么样' in query_lower and not any(keyword in query_lower for keyword in ['严重', '厉害', '程度']):
            # 如果包含"感觉"，更可能是症状询问
            if '感觉' in query_lower:
                return "症状询问"
            else:
                return "程度询问"
        else:
            return "症状询问"

    def _filter_examples_by_query_type(self, doctor_query: str, examples: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        根据查询类型筛选示例
        
        Args:
            doctor_query: 医生提问
            examples: 示例列表
            
        Returns:
            筛选后的示例列表
        """
        target_type = self._infer_query_type(doctor_query)
        filtered = []
        
        for example in examples:
            if example.get('query_type') == target_type:
                filtered.append(example)
        
        return filtered

    def _remove_duplicate_examples(self, examples: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        移除重复的示例
        
        Args:
            examples: 示例列表
            
        Returns:
            去重后的示例列表
        """
        seen = set()
        unique_examples = []
        
        for example in examples:
            # 使用示例内容作为去重的键
            key = example.get('example', '') + example.get('doctor_query', '')
            if key not in seen:
                seen.add(key)
                unique_examples.append(example)
        
        return unique_examples

    def _get_default_generic_examples(self, doctor_query: str) -> List[Dict[str, Any]]:
        """
        获取默认的通用示例
        
        Args:
            doctor_query: 医生提问
            
        Returns:
            默认示例列表
        """
        query_type = self._infer_query_type(doctor_query)
        
        default_examples = {
            "症状询问": [
                {"query_type": "症状询问", "example": "我觉得有点不舒服"}
            ],
            "时间询问": [
                {"query_type": "时间询问", "example": "大概有一段时间了"}
            ],
            "程度询问": [
                {"query_type": "程度询问", "example": "感觉一般般"}
            ],
            "伴随症状询问": [
                {"query_type": "伴随症状询问", "example": "还有一点其他症状"}
            ],
            "确认询问": [
                {"query_type": "确认询问", "example": "是的"}
            ]
        }
        
        return default_examples.get(query_type, [{"query_type": "未知", "example": "好的"}])
    

    
    def _fallback_persona_key(self, persona_key: str) -> str:
        """
        当组合未命中时，尝试回退到合适的复合人格类型
        """
        try:
            # 对于复合人格类型，尝试使用同一性格的默认情绪状态（平稳）或默认性格（合作）的同一情绪状态
            if '_' in persona_key:
                parts = persona_key.split('_')
                if len(parts) == 2:
                    # 检查是否是有效的性格和情绪值
                    valid_personalities = ['合作', '啰嗦', '怀疑', '偏执']
                    valid_emotions = ['平稳', '焦虑', '不满', '低落']
                    
                    # 如果第一部分是有效的性格，回退到该性格的默认情绪状态（平稳）
                    if parts[0] in valid_personalities:
                        fallback_key = f"{parts[0]}_平稳"
                        if fallback_key in self.persona_examples:
                            return fallback_key
                    
                    # 如果第二部分是有效的情绪状态，回退到默认性格（合作）的该情绪状态
                    if parts[1] in valid_emotions:
                        fallback_key = f"合作_{parts[1]}"
                        if fallback_key in self.persona_examples:
                            return fallback_key
        except Exception as e:
            logger.error(f"回退人格类型失败: {str(e)}")
        
        # 最终回退到默认的复合人格类型
        return "合作_平稳"
    
    def _parse_persona_profile(self, persona_config):
        """
        Parse the persona configuration to extract personality traits according to the official definition.
        
        Args:
            persona_config (dict or str): The persona configuration with standard keys matching the personality definition JSON,
                                         or a string in format "性格_情绪状态" like "合作_平稳".
            
        Returns:
            tuple: (personality_type, persona_dict)
        """
        try:
            # 性格维度优先级：合作 > 啰嗦 > 怀疑 > 偏执
            personality_priority = ['合作', '啰嗦', '怀疑', '偏执']
            # 情绪状态维度优先级：平稳 > 焦虑 > 不满 > 低落
            emotion_priority = ['平稳', '焦虑', '不满', '低落']
            
            # 处理字符串类型的输入（如 "合作_平稳"）
            if isinstance(persona_config, str):
                # 尝试解析字符串格式 "性格_情绪状态"
                if '_' in persona_config:
                    parts = persona_config.split('_')
                    if len(parts) == 2:
                        personality_value = parts[0] if parts[0] in personality_priority else "合作"
                        emotion_value = parts[1] if parts[1] in emotion_priority else "平稳"
                    else:
                        # 格式不正确，使用默认值
                        personality_value = "合作"
                        emotion_value = "平稳"
                else:
                    # 不是预期的字符串格式，使用默认值
                    personality_value = "合作"
                    emotion_value = "平稳"
                
                # 设置默认的其他维度值
                recall_value = "中"
                understanding_value = "中"
                expression_value = "中"
            else:
                # 从配置中使用人格定义文件中指定的标准键名提取各维度值
                # 同时兼容简化版键名，确保向后兼容性
                personality_value = persona_config.get("性格", "合作")
                emotion_value = persona_config.get("情绪状态", persona_config.get("情绪", "平稳"))
                recall_value = persona_config.get("病史回忆能力", persona_config.get("回忆", "中"))
                understanding_value = persona_config.get("医学理解力", persona_config.get("理解", "中"))
                expression_value = persona_config.get("语言表达能力", persona_config.get("表达", "中"))
            
            # 验证提取的值是否有效，如果无效则使用默认值
            if personality_value not in personality_priority:
                personality_value = "合作"
            if emotion_value not in emotion_priority:
                emotion_value = "平稳"
            
            # 构建人格类型键：性格_情绪状态
            persona_type = f"{personality_value}_{emotion_value}"
            
            # 构建完整的persona字典，使用人格定义文件中的标准键名
            persona_dict = {
                "性格": personality_value,
                "情绪状态": emotion_value,
                "病史回忆能力": recall_value,
                "医学理解力": understanding_value,
                "语言表达能力": expression_value
            }
            
            return persona_type, persona_dict
        except Exception as e:
            logger.error(f"Error parsing persona profile: {e}")
            # 错误处理部分也使用标准键名
            return "合作_平稳", {"性格": "合作", "情绪状态": "平稳", "病史回忆能力": "中", "医学理解力": "中", "语言表达能力": "中"}

    def rewrite_with_persona(self, neutral_answer: str, doctor_query: str, persona: Union[dict, str]) -> str:
        """
        根据人格信息将中性回答改写为个性化回答
        
        Args:
            neutral_answer: 中性回答（语义正确、未加人格特征）
            doctor_query: 医生当前提问文本
            persona: 当前患者的人格信息对象（字典格式，含五维属性）或人格类型字符串（如"合作_平稳"）
            
        Returns:
            经过人格化改写后的最终回答
        """
        try:
            # 解析人格配置，获取人格类型和完整的persona字典
            persona_type, persona_dict = self._parse_persona_profile(persona)
            
            # 检索相似的人格示例
            similar_examples = self.retrieve_similar_examples(doctor_query, persona_type)
            logger.info(f"检索到的相似示例: {similar_examples}")
            # 选择最佳示例
            best_example = self._select_best_example(similar_examples, doctor_query)
            logger.info(f"选择的最佳示例: {best_example}")
            # 构建提示词
            prompt = self._build_persona_prompt(neutral_answer, best_example, persona_type, doctor_query)
            logger.info(f"构建的提示词: {prompt}")
            # 调用模型生成（统一 messages）
            model_input = [
                {
                    "role": "system", 
                    "content": "你是一位具有特定人格特征的患者。请根据提供的人格特征，将中性回答改写为符合该人格的自然对话，保持医学信息准确的同时，体现出相应的性格和情绪特点。\n\n"
                },
                {"role": "user", "content": prompt}
            ]
            
            response = self.model_handler.generate_with_messages(model_input)
            logger.info(f"LLM输出: {response}")
            # 清理响应
            response = self._clean_persona_response(response)
            
            # 确保语义一致性
            response = self._ensure_semantic_consistency(response, neutral_answer)
            
            return response
            
        except Exception as e:
            logger.error(f"人格重写失败: {str(e)}")
            # 失败时使用模板生成作为备份
            try:
                persona_type, _ = self._parse_persona_profile(persona)
                return self._generate_with_template(neutral_answer, None, persona_type)
            except:
                return neutral_answer
    

    
    def _select_best_example(self, similar_examples: List[Dict[str, Any]], doctor_query: str) -> Optional[Dict[str, Any]]:
        """
        选择最佳示例
        
        Args:
            similar_examples: 相似示例列表
            doctor_query: 医生提问
            
        Returns:
            最佳示例
        """
        if not similar_examples:
            return None
        
        # 优先选择查询类型完全匹配的示例
        query_type = self._analyze_query_type(doctor_query)
        for example in similar_examples:
            if example.get("query_type") == query_type:
                return example
        
        # 如果没有完全匹配，返回第一个
        return similar_examples[0]
    
    def _analyze_query_type(self, doctor_query: str) -> str:
        """
        分析医生提问类型
        """
        query_lower = doctor_query.lower()
        
        if any(keyword in query_lower for keyword in ["症状", "不舒服", "疼", "痛", "难受"]):
            return "症状询问"
        elif any(keyword in query_lower for keyword in ["时间", "多久", "什么时候", "开始", "持续"]):
            return "时间询问"
        elif any(keyword in query_lower for keyword in ["程度", "严重", "厉害", "怎么样", "如何"]):
            return "程度询问"
        elif any(keyword in query_lower for keyword in ["伴随", "还有", "其他", "一起", "同时"]):
            return "伴随症状询问"
        else:
            return "一般询问"
    

    
    def _build_persona_prompt(self, neutral_response: str, best_example: Optional[Dict[str, Any]], 
                            persona_key: str, doctor_query: str) -> str:
        """
        构建人格化提示词 - 根据模块四要求优化
        参照generate_reply_prompt.py中的get_personality_description方法，确保完整包含人格定义、表现和约束信息
        """
        # 系统指令部分
        system_prompt = "你是一位具有特定人格特征的患者。请根据提供的人格特征，将中性回答改写为符合该人格的自然对话，保持医学信息准确的同时，体现出相应的性格和情绪特点。\n\n"
        
        # 问题和回答信息
        prompt = f"### 医生提问\n"
        prompt += f"{doctor_query}\n\n"
        
        prompt += f"### 中性回答\n"
        prompt += f"{neutral_response}\n\n"
        
        # 人格信息 - 结构化呈现
        prompt += "### 患者人格特征详细定义\n"
        
        # 构建人格字典，用于生成详细描述
        persona_dict = {}
        
        # 处理复合人格特征
        traits = persona_key.split("+_") if "+_" in persona_key else [persona_key]
        
        # 如果人格键格式为"性格_情绪状态"，则拆分为两部分
        if len(traits) == 1 and "_" in traits[0]:
            split_traits = traits[0].split("_")
            if len(split_traits) >= 2:
                # 假设格式为"性格_情绪状态"或"性格_情绪状态_其他"
                persona_dict["性格"] = split_traits[0]
                persona_dict["情绪状态"] = split_traits[1]
        else:
            # 对于其他格式，尝试匹配对应的维度
            for trait in traits:
                trait = trait.strip()
                for dim_id, dimension in self.personality_dimensions.items():
                    if trait in dimension['values']:
                        persona_dict[dimension['name']] = trait
                        break
        
        # 如果persona_dict为空，尝试使用默认的人格维度
        if not persona_dict and self.personality_dimensions:
            # 获取主要的人格维度
            for dim_id, dimension in self.personality_dimensions.items():
                dim_name = dimension['name']
                # 尝试从人格键中提取对应维度的值
                for trait in traits:
                    trait = trait.strip()
                    if trait in dimension['values']:
                        persona_dict[dim_name] = trait
                        break
                # 如果没有找到，使用默认值
                if dim_name not in persona_dict and dimension['values']:
                    first_value = list(dimension['values'].keys())[0]
                    persona_dict[dim_name] = first_value
        
        # 根据persona_dict生成详细的人格描述，参照generate_reply_prompt.py的实现
        descriptions = []
        
        # 遍历所有维度并添加详细信息
        for dim_id, dimension in self.personality_dimensions.items():
            dim_name = dimension['name']
            # 跳过认知状态
            if dim_name == "认知状态":
                continue
                
            # 获取当前维度的值
            current_value = persona_dict.get(dim_name)
            if not current_value:
                # 如果没有值，使用默认值
                if dimension['values']:
                    current_value = list(dimension['values'].keys())[0]
                else:
                    continue
            
            dim_key_name = dimension.get("key", dim_name)
            values_info = dimension.get("values", {})
            value_info = values_info.get(current_value, {})
            
            desc_parts = [f"{dim_name}（{dim_key_name}）: {current_value}"]
            
            # 添加定义信息
            if "定义" in value_info:
                desc_parts.append(f"  - 定义：{value_info['定义']}")
            
            # 添加表现信息
            if "表现" in value_info:
                desc_parts.append(f"  - 表现：{value_info['表现']}")
            
            # 添加约束信息
            if "约束" in value_info:
                constraint = value_info['约束']
                if isinstance(constraint, dict):
                    constraint_text = []
                    for k, v in constraint.items():
                        if isinstance(v, dict):
                            constraint_text.append(f"{k}: {', '.join([f'{subk}: {subv}' for subk, subv in v.items()])}")
                        elif isinstance(v, list):
                            constraint_text.append(f"{k}: {', '.join(v)}")
                        else:
                            constraint_text.append(f"{k}: {v}")
                    desc_parts.append(f"  - 约束：{'; '.join(constraint_text)}")
                else:
                    desc_parts.append(f"  - 约束：{constraint}")
            
            # 添加表现形式示例
            if "表现形式示例" in value_info:
                desc_parts.append(f"  - 表现形式示例：{'; '.join(value_info['表现形式示例'])}")
            
            descriptions.append('\n'.join(desc_parts))
        
        if descriptions:
            prompt += "\n".join(descriptions)
            prompt += "\n\n"
        
        # 参考示例
        if best_example and isinstance(best_example, dict) and "example" in best_example:
            prompt += f"### 参考示例\n"
            prompt += f"{best_example['example']}\n\n"
            if "description" in best_example:
                prompt += f"示例说明：{best_example['description']}\n\n"
        
        # 改写要求 - 更明确的指导
        prompt += "### 改写要求\n"
        prompt += "1. **保持医学事实准确性**：所有症状、时间、程度等医学信息必须与中性回答一致\n"
        prompt += "2. **体现人格特征**：语言风格、语气、表达方式必须符合指定的人格类型\n"
        prompt += "3. **自然对话感**：回答应像真实患者的日常口语表达，避免生硬\n"
        prompt += "4. **情感一致性**：复合人格时，确保不同人格特征的情感表达协调一致\n"
        prompt += "5. **简洁明了**：在体现人格特征的同时，避免过度冗长（除非人格特征为啰嗦）\n\n"
        
        # 输出格式要求
        prompt += "### 输出格式\n"
        prompt += "请直接输出改写后的回答，不要添加任何前缀或后缀，确保回答流畅自然。\n\n"
        
        prompt += "### 改写后的回答\n"
        
        return system_prompt + prompt
    
    def _clean_persona_response(self, response: str) -> str:
        """
        清理人格化响应
        """
        # 移除可能的前缀
        prefixes_to_remove = ["患者：", "患者回答：", "回答：", "患者说：", "改写后的回答："]
        for prefix in prefixes_to_remove:
            if response.startswith(prefix):
                response = response[len(prefix):].strip()
        
        # 移除多余的标点
        response = response.strip()
        if response.endswith("。"):
            response = response[:-1]
        
        return response
    
    def _generate_with_template(self, neutral_response: str, best_example: Optional[Dict[str, Any]], 
                              persona_key: str) -> str:
        """
        使用模板生成人格化回答 - 根据模块四要求实现
        
        Args:
            neutral_response: 中性回答
            best_example: 最佳示例
            persona_key: 人格类型键
            
        Returns:
            人格化回答
        """
        try:
            # 保存原始回答用于多重人格特征的叠加应用
            original_response = neutral_response
            
            # 如果有最佳示例，优先参考示例的结构和表达方式
            if best_example and isinstance(best_example, dict) and "example" in best_example:
                example_text = best_example["example"]
                # 分析示例的风格特征
                example_style = self._analyze_example_style(example_text)
                # 根据示例风格调整生成策略
                neutral_response = self._adjust_by_example(neutral_response, example_style)
            
            # 处理复合人格特征（格式：性格+情绪状态）
            if "+_" in persona_key:
                traits = persona_key.split("+_")
                # 确保去重
                traits = list(dict.fromkeys(trait.strip() for trait in traits))
                
                # 定义特征优先级：先应用性格特征，再应用情绪状态特征
                personality_order = {"合作": 1, "怀疑": 1, "偏执": 1, "啰嗦": 1, 
                                   "低落": 2, "焦虑": 2, "不满": 2, "平稳": 2, "积极": 2}
                
                # 按优先级排序特征
                sorted_traits = sorted(traits, key=lambda x: personality_order.get(x, 999))
                
                # 依次应用特征
                for trait in sorted_traits:
                    if trait == "怀疑":
                        neutral_response = self._apply_suspicious_style(neutral_response)
                    elif trait == "合作":
                        neutral_response = self._apply_cooperative_style(neutral_response)
                    elif trait == "偏执":
                        neutral_response = self._apply_paranoid_style(neutral_response)
                    elif trait == "啰嗦":
                        neutral_response = self._apply_verbose_style(neutral_response)
                    elif trait == "低落":
                        neutral_response = self._apply_depressed_style(neutral_response)
                    elif trait == "焦虑":
                        neutral_response = self._apply_anxious_style(neutral_response)
                    elif trait == "不满":
                        neutral_response = self._apply_dissatisfied_style(neutral_response)
                    elif trait == "积极":
                        neutral_response = self._apply_positive_style(neutral_response)
                
                return neutral_response
            # 处理单一人格特征
            elif persona_key == "怀疑":
                return self._apply_suspicious_style(neutral_response)
            elif persona_key == "低落":
                return self._apply_depressed_style(neutral_response)
            elif persona_key == "合作":
                return self._apply_cooperative_style(neutral_response)
            elif persona_key == "积极":
                return self._apply_positive_style(neutral_response)
            elif persona_key == "偏执":
                return self._apply_paranoid_style(neutral_response)
            elif persona_key == "啰嗦":
                return self._apply_verbose_style(neutral_response)
            elif persona_key == "焦虑":
                return self._apply_anxious_style(neutral_response)
            elif persona_key == "不满":
                return self._apply_dissatisfied_style(neutral_response)
            elif persona_key == "平稳":
                # 平稳情绪不需要特别处理
                return neutral_response
            else:
                return neutral_response
                
        except Exception as e:
            logger.warning(f"模板人格化生成失败: {str(e)}")
            return neutral_response
            
    def _analyze_example_style(self, example_text: str) -> Dict[str, Any]:
        """
        分析示例文本的风格特征
        
        Args:
            example_text: 示例文本
            
        Returns:
            风格特征字典
        """
        style_features = {
            "has_hesitation": any(expr in example_text for expr in ["大概", "可能", "记不太清", "说不准"]),
            "has_negativity": any(expr in example_text for expr in ["唉", "越来越严重", "没希望", "治了也没用"]),
            "has_positivity": any(expr in example_text for expr in ["没什么大问题", "会好起来", "感觉好多了"]),
            "has_cooperation": any(expr in example_text for expr in ["好的", "是这样的", "我详细说一下"]),
            "has_paranoia": any(expr in example_text for expr in ["肯定有问题", "你们要重视", "我查过资料"]),
            "is_verbose": len(example_text) > 50 or "然后" in example_text or "还有" in example_text,
            "has_anxiety": any(expr in example_text for expr in ["担心", "害怕", "怎么办"]),
            "has_dissatisfaction": any(expr in example_text for expr in ["真是的", "太麻烦", "早知道"])
        }
        return style_features
    
    def _adjust_by_example(self, neutral_response: str, example_style: Dict[str, Any]) -> str:
        """
        根据示例风格调整回答
        
        Args:
            neutral_response: 中性回答
            example_style: 示例风格特征
            
        Returns:
            调整后的回答
        """
        # 根据示例风格特征进行调整
        if example_style["has_hesitation"] and not any(expr in neutral_response for expr in ["大概", "可能"]):
            # 添加犹豫表达
            hesitation_exprs = ["，大概", "，可能", "，我也说不准"]
            import random
            if "。" in neutral_response:
                neutral_response = neutral_response.replace("。", random.choice(hesitation_exprs) + "。")
        
        if example_style["has_negativity"] and "唉" not in neutral_response:
            # 添加消极表达
            if "。" in neutral_response:
                neutral_response = neutral_response.replace("。", "，唉。")
        
        if example_style["has_cooperation"] and not neutral_response.startswith("好的"):
            # 添加合作性开头
            neutral_response = "好的，" + neutral_response
        
        if example_style["is_verbose"] and len(neutral_response) < 50:
            # 适当扩展为更啰嗦的表达
            verbose_exprs = ["，你知道吗", "，跟我说的", "，其实啊"]
            import random
            if "。" in neutral_response:
                neutral_response = neutral_response.replace("。", random.choice(verbose_exprs) + "。")
        
        return neutral_response
    
    def _apply_suspicious_style(self, neutral_response: str) -> str:
        """
        应用怀疑型风格 - 根据人格定义和交互矩阵
        """
        # 根据人格定义：对医生的问诊保持一定程度的不信任，在部分问题上提出质疑或反问
        怀疑_expressions = [
            "，但我也说不准",
            "，真的是这样吗",
            "，会不会是其他问题呢",
            "，我觉得可能不太对",
            "，您确定吗"
        ]
        
        # 随机选择一个怀疑性表达添加到句尾
        import random
        if "。" in neutral_response:
            neutral_response = neutral_response.replace("。", random.choice(怀疑_expressions) + "。")
        
        return neutral_response
    
    def _apply_depressed_style(self, neutral_response: str) -> str:
        """
        应用低落型风格 - 根据人格定义和交互矩阵
        """
        # 根据人格定义：情绪消沉、缺乏积极性，语气低沉，缺乏热情
        低落_expressions = [
            "，唉，也不知道什么时候能好",
            "，反正就是这样了",
            "，没什么希望了",
            "，治了也没用",
            "，唉"
        ]
        
        # 随机选择一个低落性表达添加到句尾
        import random
        if "。" in neutral_response:
            neutral_response = neutral_response.replace("。", random.choice(低落_expressions) + "。")
        elif not neutral_response.endswith("，"):
            neutral_response += random.choice(低落_expressions)
        
        return neutral_response
    
    def _apply_cooperative_style(self, neutral_response: str) -> str:
        """
        应用合作型风格 - 根据人格定义和交互矩阵
        """
        # 根据人格定义：的合作者，愿意回答问题，回答自然、简洁
        合作_expressions = [
            "好的，",
            "是的，",
            "没问题，",
            "我详细说一下，",
            "是这样的，"
        ]
        
        # 添加合作性开头
        import random
        if not any(neutral_response.startswith(expr) for expr in 合作_expressions):
            neutral_response = random.choice(合作_expressions) + neutral_response
        
        return neutral_response
    
    def _apply_positive_style(self, neutral_response: str) -> str:
        """
        应用积极型风格
        """
        # 添加积极性表达
        积极_expressions = [
            "，应该没什么大问题",
            "，会好起来的",
            "，感觉到还可以",
            "，没关系的",
            "，放心吧"
        ]
        
        import random
        if "。" in neutral_response:
            neutral_response = neutral_response.replace("。", random.choice(积极_expressions) + "。")
        
        return neutral_response
    
    def _apply_paranoid_style(self, neutral_response: str) -> str:
        """
        应用偏执型风格 - 根据人格定义和交互矩阵
        """
        # 根据人格定义：坚持自己的观点或解释，回答时会固执己见
        偏执_expressions = [
            "，我觉得就是这样",
            "，肯定没错",
            "，我自己的身体我清楚",
            "，我就知道是这个问题",
            "，不用检查了，肯定是这样"
        ]
        
        import random
        if "。" in neutral_response:
            neutral_response = neutral_response.replace("。", random.choice(偏执_expressions) + "。")
        
        return neutral_response
    
    def _apply_verbose_style(self, neutral_response: str) -> str:
        """
        应用啰嗦型风格 - 根据人格定义和交互矩阵
        """
        # 根据人格定义：在交流中倾向于说得较多，包含一些与病情无关的小细节
        啰嗦_expressions = [
            "，你知道吗，昨天我还...",
            "，还有啊，跟我说的...",
            "，说起这个，我想起...",
            "，对了，差点忘了说...",
            "，其实啊，之前..."
        ]
        
        import random
        if len(neutral_response) < 50:  # 只对较短的回答添加啰嗦内容
            if "。" in neutral_response:
                neutral_response = neutral_response.replace("。", random.choice(啰嗦_expressions) + "。")
        
        return neutral_response
    
    def _apply_anxious_style(self, neutral_response: str) -> str:
        """
        应用焦虑型风格 - 根据人格定义和交互矩阵
        """
        # 根据人格定义：对病情存在担忧和紧张，可能出现追问、重复确认或用紧张词汇
        焦虑_expressions = [
            "，我很担心",
            "，不会有什么大问题吧",
            "，是不是很严重啊",
            "，我好害怕",
            "，怎么办啊"
        ]
        
        import random
        if "。" in neutral_response:
            neutral_response = neutral_response.replace("。", random.choice(焦虑_expressions) + "。")
        
        return neutral_response
    
    def _apply_dissatisfied_style(self, neutral_response: str) -> str:
        """
        应用不满型风格 - 根据人格定义和交互矩阵
        """
        # 根据人格定义：对就诊过程或结果有不满情绪，语气生硬，偶尔表现出抱怨或质疑
        不满_expressions = [
            "，真是的",
            "，怎么会这样",
            "，太麻烦了",
            "，等了这么久",
            "，早知道这样..."
        ]
        
        import random
        if "。" in neutral_response:
            neutral_response = neutral_response.replace("。", random.choice(不满_expressions) + "。")
        
        return neutral_response
    
    def _ensure_semantic_consistency(self, persona_response: str, neutral_response: str) -> str:
        """
        确保语义一致性
        
        Args:
            persona_response: 人格化回答
            neutral_response: 中性回答
            
        Returns:
            确保一致性的回答
        """
        try:
            # 简单的语义一致性检查
            # 检查是否包含关键医学信息
            neutral_keywords = self._extract_keywords(neutral_response)
            persona_keywords = self._extract_keywords(persona_response)
            
            # 如果人格化回答丢失了太多关键信息，进行修正
            missing_keywords = neutral_keywords - persona_keywords
            if len(missing_keywords) > len(neutral_keywords) * 0.3:  # 丢失超过30%的关键词
                logger.warning("人格化回答可能丢失了关键信息，尝试修正")
                # 简单的修正：在人格化回答后添加缺失信息
                missing_info = "，".join(missing_keywords)
                if missing_info:
                    persona_response += f"，{missing_info}"
            
            return persona_response
            
        except Exception as e:
            logger.warning(f"语义一致性检查失败: {str(e)}")
            return persona_response
    
    def _extract_keywords(self, text: str) -> set:
        """
        提取文本关键词
        """
        # 扩展的医学关键词提取
        keywords = set()
        
        # 常见症状关键词
        symptoms = [
            "疼", "痛", "咳嗽", "发热", "头痛", "腹痛", "恶心", "呕吐", "腹泻", "便秘",
            "头晕", "胸闷", "乏力", "气短", "心悸", "失眠", "皮疹", "瘙痒", "肿胀", "麻木",
            "出血", "鼻塞", "咽痛", "耳鸣", "视力模糊", "关节痛", "肌肉痛", "呼吸困难", "食欲不振"
        ]
        
        # 时间关键词
        time_terms = ["今天", "昨天", "前天", "一周", "两周", "一个月", "两个月", "三个月",
                     "早上", "下午", "晚上", "夜间", "持续", "间歇性", "偶尔", "经常", "总是"]
        
        # 程度关键词
        severity_terms = ["轻微", "轻度", "中度", "重度", "严重", "剧烈", "强烈", "明显",
                         "有点", "稍微", "很", "非常", "特别", "极其", "不太", "不太明显"]
        
        # 药物关键词
        medication_terms = ["药", "药片", "胶囊", "口服液", "抗生素", "退烧药", "止痛药",
                          "阿司匹林", "布洛芬", "对乙酰氨基酚", "头孢", "青霉素", "中药", "西药"]
        
        # 检查关键词
        examination_terms = ["检查", "化验", "CT", "X光", "B超", "血常规", "尿常规", "心电图",
                           "血压", "血糖", "体温", "脉搏", "体重"]
        
        # 收集所有关键词列表
        all_keywords = symptoms + time_terms + severity_terms + medication_terms + examination_terms
        
        for term in all_keywords:
            if term in text:
                keywords.add(term)
        
        return keywords

    def _load_persona_examples(self) -> Dict[str, Dict]:
        """
        加载人格示例库，返回符合模块四要求的结构
        
        Returns:
            人格示例库字典，格式为 {"性格_情绪状态": {"samples": [...], "embedding_index": "..."}}
        """
        try:
            if not os.path.exists(self.persona_examples_path):
                logger.warning(f"人格示例库文件不存在: {self.persona_examples_path}")
                return self._get_default_examples()
            
            with open(self.persona_examples_path, 'r', encoding='utf-8') as f:
                examples = json.load(f)
            
            logger.info(f"成功加载人格示例库，包含 {len(examples)} 种人格类型")
            return examples
            
        except Exception as e:
            logger.error(f"加载人格示例库失败: {str(e)}")
            return self._get_default_examples()

    def _get_default_examples(self) -> Dict[str, Dict]:
        """
        获取默认人格示例 - 符合模块四要求的复合人格类型结构
        """
        # 创建4x4=16种复合人格类型的默认示例
        personalities = ['合作', '啰嗦', '怀疑', '偏执']
        emotions = ['平稳', '焦虑', '不满', '低落']
        
        default_examples = {}
        
        for personality in personalities:
            for emotion in emotions:
                persona_key = f"{personality}_{emotion}"
                
                # 根据不同性格设置不同的回忆、理解、表达参数
                recall = "高" if personality in ['合作', '啰嗦'] else "中"
                understanding = "高" if personality in ['合作', '怀疑'] else "中"
                expression = "高" if personality in ['合作', '啰嗦'] else "中"
                
                # 根据情绪状态设置不同的回答风格
                if emotion == "平稳":
                    answer_tone = "平静地回答"
                elif emotion == "焦虑":
                    answer_tone = "有些焦虑地回答"
                elif emotion == "不满":
                    answer_tone = "不满地回答"
                else:  # 低落
                    answer_tone = "低落地回答"
                
                default_examples[persona_key] = {
                    "samples": [
                        {
                            "doctor_query": "最近咳嗽有没有好一些？",
                            "patient_answer": f"{answer_tone}：咳嗽少了点，不过晚上还会有几声。",
                            "persona": {"性格": personality, "情绪": emotion, "回忆": recall, "理解": understanding, "表达": expression},
                            "entities": ["咳嗽", "晚上"]
                        },
                        {
                            "doctor_query": "这种症状持续多久了？",
                            "patient_answer": f"{answer_tone}：大概有一个星期左右了。",
                            "persona": {"性格": personality, "情绪": emotion, "回忆": recall, "理解": understanding, "表达": expression},
                            "entities": ["一个星期"]
                        }
                    ],
                    "embedding_index": f"data/embeddings/{persona_key}.index"
                }
        
        return default_examples

    def _call_llm(self, system_prompt: str, prompt_template: str, similar_examples: List[Dict[str, Any]]) -> str:
        """
        调用LLM进行人格化改写
        
        Args:
            system_prompt: 系统提示
            prompt_template: 提示模板
            similar_examples: 相似示例列表
            
        Returns:
            改写后的回答
        """
        try:
            if self.model_handler and hasattr(self.model_handler, 'generate_with_messages'):
                # 构建完整的消息
                messages = [
                    {'role': 'system', 'content': system_prompt},
                    {'role': 'user', 'content': prompt_template}
                ]
                
                # 如果有相似示例，添加到消息中
                if similar_examples:
                    examples_text = "参考示例：\n"
                    for i, example in enumerate(similar_examples[:3]):  # 最多使用3个示例
                        if isinstance(example, dict) and 'example' in example:
                            examples_text += f"{i+1}. {example['example']}\n"
                    if examples_text != "参考示例：\n":
                        # 在用户消息前添加示例信息
                        messages[1]['content'] = examples_text + "\n" + messages[1]['content']
                
                # 调用模型生成
                response = self.model_handler.generate_with_messages(messages)
                return response
            else:
                # 如果没有model_handler，返回空字符串
                logger.warning("No model handler available for LLM generation")
                return ""
                
        except Exception as e:
            logger.error(f"LLM调用失败: {str(e)}")
            return ""
